iT邦幫忙

2021 iThome 鐵人賽

DAY 25
0
Modern Web

看初心者怎麼學React系列 第 25

Day25 React useReducer - 另種管理state的方法

  • 分享至 

  • xImage
  •  

useReducer和useState都是用於資料狀態管理的Hook,
那我該怎麼區分使用他們的時機呢?

useState
適合用於不受其他state影響的獨立資料狀態。

useReducer
適合用於受其他較多條件影響、複雜的資料狀態。

我們多將 useReducercontext API 用來做全域共用state的管理,
透過ruducer函式裡的判斷條件來更新state,更方便集中管理邏輯複雜的state。


useReducer使用方法

第一步:引入useReducer

//App.js

import React, { useReducer } from 'react';

第二步:自定初始的State資料

//我設資料初始值為物件,裡面帶兩個之後要使用的值
const setValue = {
  text: "黑色", color: 'black'
}

第三步:建立 reducer

自定義判斷資料更新的ruducer函式,有兩個參數state、action可以使用,根據action條件的不同,決定返回的新state資料。

  • state:使用seReducer()返回的的目前state狀態()
  • action:利用useReducer中類似setState的資料更新函式 (dispatch) 帶入的字串或物件,來判斷資料更新邏輯。
//自定義的reducer函式
function reducer(state, action) {

//判斷action等於dispatch帶入的參數,我取裡面的type值做更新判斷
  switch (action.type) {
    case 'red':
      return {
        text: '紅色', color: action.type
      }
    case 'blue':
      return {
        text: '藍色', color: action.type
      }
    default:
      return state;
  }
}

第四步:在元件function內宣告使用useReducer

其中兩個傳入的參數為

  • reducer:
    第三步建立的reducer函式,讓useReducer可以根據它返回正確要更新的資料。

  • setValue:
    第一步設立的初始資料格式。

//const [state, dispatch] = useReducer(reducer函式, 初始資料);

//照前面步驟的設定放入參數
const [state, dispatch] = useReducer(reducer, setValue);

而我們宣告的變數(可自訂)分別是:

  • state:
    這裡的state可以在jsx上用props傳入子元件,或是搭配上上篇的context設定全域state。

  • dispatch:
    接收action參數的函式,我們會根據傳入的action,帶入第三步的ruducer做判斷返回更新state給useReducer的state

第五步:使用dispatch傳入條件做資料更新

這樣點擊更新資料後,我們就可以利用useReducer保存的state了,
在這邊我們將state傳入context做全域資料,讓下兩層的子元件使用。

function App() {

//
  const [state, dispatch] = useReducer(reducer, setValue);

  return (
    <div className="App">

		//點擊按鈕後使用dispatch傳入action到ruducer函式做條件判斷(action的值也可以用物件傳入)
        <button onClick={() => dispatch({ type: 'red' })}>切到紅色</button>
        <button onClick={() => dispatch({ type: 'blue' })}>切到藍色</button>

			//將useReducer的state資料傳入context
        <ContextState.Provider value={state}>
          <Child />
        </ContextState.Provider>
    </div >)

}

最後呈現的效果如下:


全部的程式碼:

App.js

import React, { useReducer } from 'react';
import './App.css';
import { ContextState } from './context/ContextState.js'
import Child from './component/Child';

const setValue = {
  text: "黑色", color: 'black'
}

function reducer(state, action) {
  switch (action.type) {
    case 'red':
      return {
        text: '紅色', color: action.type
      }
    case 'blue':
      return {
        text: '藍色', color: action.type
      }
    default:
      return state;
  }
}

//元件function
function App() {

  const [state, dispatch] = useReducer(reducer, setValue);

  return (
    <div className="App">
     
        <button onClick={() => dispatch({ type: 'red' })}>切到紅色</button>
        <button onClick={() => dispatch({ type: 'blue' })}>切到藍色</button>
//context
        <ContextState.Provider value={state}>
          <Child />
        </ContextState.Provider>
    </div >)

}

export default App;

Child.js

import React from 'react';
import './Child.css'
import Grandson from './Grandson'

function Child() {

    return (
        <div className="App child-wrap" >
            <h4>Child元件用不到context</h4>
            <Grandson />
        </div>)

}

export default Child;

Grandson.js

import React, { useContext } from 'react';
import { ContextState } from '../context/ContextState'

function Grandson() {
    const getContext = useContext(ContextState)
    const styleColor = { color: getContext.color }

    return (
        <div className="App grandson-wrap" >
            Grandson元件使用Context
            <br />
            <div style={styleColor}>{getContext.text}</div>

        </div >)

}

export default Grandson;

上一篇
Day24 React useContext-在子元件使用context
下一篇
Day26 React-實作todoList(一)前置
系列文
看初心者怎麼學React30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言